package com.zj.baseproxy.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import com.zj.baseproxy.config.register.ImportBeanDefinitionRegister;
import com.zj.baseproxy.interfaces.BeanCreateRule;
import com.zj.baseproxy.interfaces.HttpHandler;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.NamingStrategy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.InvocationHandlerAdapter;
import net.bytebuddy.matcher.ElementMatchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * @author 19242
 */
@Import(ImportBeanDefinitionRegister.class)
@Configuration
public class ProxyBeanConfig {

    private static final Logger log = LoggerFactory.getLogger(ProxyBeanConfig.class);

    @Bean
    @ConditionalOnMissingBean(name = "beanCreateRule")
    public BeanCreateRule beanCreateRule() {
        return new BeanCreateRule() {
            @Override
            public <T> T create(Class<T> clazz) {
                // 使用byte-buddy动态代理接口
                Object o = null;
                try {
                    o = new ByteBuddy().with(new NamingStrategy.AbstractBase() {
                                @Override
                                protected String name(TypeDescription typeDescription) {
                                    return "com.zj.baseproxy.template.service.impl." + clazz.getSimpleName() + "Impl";
                                }
                            })
                            .subclass(Object.class)
                            .implement(clazz)
                            // 拦截除了Object的方法，也就是所有未实现的方法
                            .method(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)))
                            .intercept(InvocationHandlerAdapter.of((o1, method, objects) -> null))
                            .make()
                            .load(clazz.getClassLoader())
                            .getLoaded()
                            .newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    log.warn("bean生成失败", e);
                }
                return clazz.cast(o);
            }
        };
    }

    @Bean
    @ConditionalOnMissingBean(name = "httpHandler", value = HttpHandler.class)
    public HttpHandler httpHandler() {
        return (typeEnum, url, json, headerMap) -> {
            HttpRequest httpRequest = HttpRequest.post(url)
                    .contentType(ContentType.JSON.toString());
            if (CollectionUtil.isNotEmpty(headerMap)) {
                headerMap.forEach(httpRequest::header);
            }
            return httpRequest.body(json)
                    .execute()
                    .body();
        };
    }

}
